package com.tacuati.ui;

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.TransferHandler;
import javax.swing.tree.TreePath;

import com.tacuati.content.Collection;
import com.tacuati.content.Content;
import com.tacuati.content.Item;

class ContentTreeTransferHandler extends TransferHandler {

	private static final long serialVersionUID = 1L;

	DataFlavor nodesFlavor;
	DataFlavor[] flavors = new DataFlavor[1];
	List<Object> nodesToRemove = new ArrayList<Object>();

	public ContentTreeTransferHandler() {
		try {
			String mimeType = DataFlavor.javaJVMLocalObjectMimeType + ";class=\"" + Item[].class.getName() + "\"";
			nodesFlavor = new DataFlavor(mimeType);
			flavors[0] = nodesFlavor;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public boolean canImport(TransferHandler.TransferSupport support) {
		
		if (support.isDrop()) { // Drop		
			if (!support.isDataFlavorSupported(nodesFlavor)) {
				return false;
			}

			support.setShowDropLocation(true);
			Object dropObject = ((JTree.DropLocation) support.getDropLocation()).getPath().getLastPathComponent();

			if (dropObject instanceof Collection || dropObject instanceof Content) {
				return true;
			}
		} else {
			JTree tree = (JTree) support.getComponent();
			if ( tree.getSelectionPaths()==null || tree.getSelectionPaths()[0].getLastPathComponent() instanceof Collection) {
				return true;
			}
		}
		return false;
	}

	protected Transferable createTransferable(JComponent c) {
		JTree tree = (JTree) c;
		TreePath[] paths = tree.getSelectionPaths();

		List<Item> nodes = new ArrayList<Item>();
		nodesToRemove.clear();
		
		if (paths!=null){
			for (TreePath path : paths) {
				try {
					Item i = (Item) path.getLastPathComponent();
					Object p = path.getParentPath().getLastPathComponent();
					Object[] toRemoveItem = new Object[]{i,p};
					nodes.add(i);
					nodesToRemove.add(toRemoveItem);
				} catch (Exception e) {
				}
			}
	
			if (nodes.size() > 0) {
				return new ItemsTransferable(nodes);
			}
		}
		return null;
	}

	protected void exportDone(JComponent source, Transferable data, int action) {
		if (action == MOVE || action == NONE) {
			JTree tree = (JTree) source;
			ContentTreeModel model = (ContentTreeModel) tree.getModel();

			int i = 0;
			for (Object object : nodesToRemove) {
				Object[] ob = (Object[]) object;
				model.removeNodeFromParent((Item) ob[0], ob[1]);
				i++;
			}
			nodesToRemove.clear();
		}
	}

	public int getSourceActions(JComponent c) {
		return COPY_OR_MOVE;
	}

	public boolean importData(TransferHandler.TransferSupport support) {
		if (!canImport(support)) {
			return false;
		}

		Item[] nodes = null;
		try {
			Transferable t = support.getTransferable();
			nodes = (Item[]) t.getTransferData(nodesFlavor);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		TreePath dest=null;
		if (support.isDrop()){
			JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation();
			dest = dl.getPath();
		} else {
			JTree tree = (JTree) support.getComponent();
			if (tree.getSelectionPaths()!=null){
				dest = tree.getSelectionPaths()[0];
			}
		}

		ContentTreeNode parent = null;
		parent = (ContentTreeNode) dest.getLastPathComponent();

		JTree tree = (JTree) support.getComponent();
		ContentTreeModel model = (ContentTreeModel) tree.getModel();

		for (Item item : nodes) {
			model.insertNodeInto(item, parent);
		}
		return true;
	}

	public String toString() {
		return getClass().getName();
	}

	public class ItemsTransferable implements Transferable {
		Item[] data;

		public ItemsTransferable(List<Item> nodes) {
			this.data = nodes.toArray(new Item[nodes.size()]);
		}

		public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
			if (!isDataFlavorSupported(flavor))
				throw new UnsupportedFlavorException(flavor);

			return data;
		}

		public DataFlavor[] getTransferDataFlavors() {
			return flavors;
		}

		public boolean isDataFlavorSupported(DataFlavor flavor) {
			return nodesFlavor.equals(flavor);
		}
	}
}